package com.cloud.common.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;

@Slf4j
public class DateTimeUtils {
    public static final String TIME_FORMAT = "HH:mm:ss";
    public static final String DATE_FORMAT = "yyyy-MM-dd";
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public static String toDateString(Date date) {
        return asLocalDate(date).format(DateTimeFormatter.ofPattern(DATE_FORMAT));
    }

    public static String toDateString(LocalDate localDate) {
        return localDate.format(DateTimeFormatter.ofPattern(DATE_FORMAT));
    }

    public static String toDateString(LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ofPattern(DATE_FORMAT));
    }

    public static String toDateTimeString(Date date) {
        return asLocalDateTime(date).format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT));
    }

    public static String toDateTimeString(LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT));
    }

    public static LocalTime asLocalTime(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime().toLocalTime();
    }

    public static LocalDate asLocalDate(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static LocalDateTime asLocalDateTime(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static Date asDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date asDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 时间格式检查
     *
     * @param timeStr 时间值
     * @param timeFormat null则使用默认格式
     * @return
     */
    public static boolean checkTimeFormat(String timeStr, String timeFormat) {
        try {
            timeFormat = timeFormat == null ? TIME_FORMAT : timeFormat;
            LocalTime.parse(timeStr, DateTimeFormatter.ofPattern(timeFormat));
            return true;
        } catch (Exception e) {
            log.warn("checkTimeFormat failure, timeStr={}", timeStr);
        }
        return false;
    }

    /**
     * 日期格式检查
     *
     * @param dateStr 日期值
     * @param dateFormat null则使用默认格式
     * @return
     */
    public static boolean checkDateFormat(String dateStr, String dateFormat) {
        try {
            dateFormat = dateFormat == null ? DATE_FORMAT : dateFormat;
            LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(dateFormat));
            return true;
        } catch (Exception e) {
            log.warn("checkDateFormat failure, dateStr={}", dateStr);
        }
        return false;
    }

    /**
     * 日期时间格式检查
     *
     * @param dateTimeStr 日期时间值
     * @param dateTimeFormat null则使用默认格式
     * @return
     */
    public static boolean checkDateTimeFormat(String dateTimeStr, String dateTimeFormat) {
        try {
            dateTimeFormat = dateTimeFormat == null ? DATE_TIME_FORMAT : dateTimeFormat;
            LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(dateTimeFormat));
            return true;
        } catch (Exception e) {
            log.warn("checkDateTimeFormat failure, dateTimeStr={}", dateTimeStr);
        }
        return false;
    }

    /**
     * 计算2个时间的间隔秒数
     *
     * @param startTimeStr
     * @param endTimeStr
     * @return long
     */
    public static long betweenSeconds(String startTimeStr, String endTimeStr) {
        if (StringUtils.isEmpty(startTimeStr) || StringUtils.isEmpty(endTimeStr)) {
            return 0;
        }
        LocalTime startTime = LocalTime.parse(startTimeStr);
        LocalTime endTime = LocalTime.parse(endTimeStr);
        return Duration.between(startTime, endTime).getSeconds();
    }

    /**
     * 计算年龄
     *
     * @param birthDate 出生日期
     * @return int
     */
    public static int computeAge(Date birthDate) {
        LocalDate birthTime = DateTimeUtils.asLocalDate(birthDate);
        LocalDate currentTime = DateTimeUtils.asLocalDate(new Date());
        int birthYear = birthTime.getYear();
        int currentYear = currentTime.getYear();
        int age = currentYear - birthYear;

        if (currentTime.getMonthValue() > birthTime.getMonthValue()) {
            return age;
        }
        if (currentTime.getDayOfMonth() >= birthTime.getDayOfMonth()) {
            return age;
        }
        return --age;
    }
}
